package com.code.impl;

import com.code.CodeWriter;
import com.code.helper.ProjectHelper;
import com.common.config.ProjectConfig;
import com.common.entity.CClass;
import com.common.entity.CField;
import com.common.entity.CMethod;
import com.sqlsession.database.DbType;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class EntryCodeWrite extends CodeWriter {

    private static final String PATH = "pojo/po";

    public EntryCodeWrite(ProjectConfig projectConfig) {
        super(projectConfig);
    }

    @Override
    public void write(CClass cClass) {
        StringBuilder builder = new StringBuilder();
        String prefix = "";
        builder.append("package ").append(ProjectHelper.getBaseCodePackage(getProjectConfig(), PATH)).append(";").append("\n\n");
        Set<String> imports = cClass.getImports();
        for (String anImport : imports) {
            builder.append("import ").append(anImport).append(";").append("\n");
        }
        builder.append("\n\n");
        appendDoc(prefix, builder, cClass.getCommon());
        Map<String, Map<String, String>> annotations = cClass.getAnnotations();
        appendAnnotations_(prefix, builder, annotations);

        builder.append("public class ").append(cClass.getName()).append(" {");
        builder.append("\n");
        builder.append("\n");
        List<CField> cFields = cClass.getcFields();
        if (cFields != null) {
            for (CField cField : cFields) {
                builder.append("\n");
                prefix = "    ";
                appendDoc(prefix, builder, cField.getCommon());
                Map<String, Map<Set<String>, String>> fieldAnnotations = cField.getAnnotations();
                appendAnnotations(prefix, builder, fieldAnnotations);
                Map<String, String> classType = cField.getClassType();
                for (Map.Entry<String, String> entry : classType.entrySet()) {
                    builder.append(prefix).append(cField.getModifier()).append(" ").append(entry.getKey()).append(" ").append(cField.getName()).append(";");
                }
                builder.append("\n");
                builder.append("\n");
            }
        }
        List<CMethod> cMethods = cClass.getcMethods();
        if (cMethods != null) {
            prefix = "    ";
            for (CMethod cMethod : cMethods) {
                Map<String, Map<String, String>> cMethodAnnotations = cMethod.getAnnotations();
                appendAnnotations_(prefix, builder, cMethodAnnotations);
                builder.append(prefix).append(cMethod.getMethodName());
                builder.append("\n");
                builder.append(prefix).append("{").append("\n");
                builder.append(prefix + "  ").append(cMethod.getBody()).append("\n");
                builder.append(prefix).append("}").append("\n").append("\n");
            }
        }
        builder.append(" }");
        String cachePath = ProjectHelper.getBaseCodePath(getProjectConfig(), PATH);
        File cache = new File(cachePath);
        if (!cache.exists()) {
            cache.mkdirs();
        }
        File file = new File(cache, cClass.getName() + ".java");
        try {
            FileWriter fileWriter = new FileWriter(file);
            fileWriter.write(builder.toString());
            fileWriter.flush();
            fileWriter.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Deprecated
    private void appendAnnotations_(String prefix, StringBuilder builder, Map<String, Map<String, String>> annotations) {
        if (annotations != null) {
            for (Map.Entry<String, Map<String, String>> entry : annotations.entrySet()) {
                builder.append(prefix).append(entry.getKey()).append("(");
                for (Map.Entry<String, String> stringEntry : entry.getValue().entrySet()) {
                    builder.append(stringEntry.getValue());
                }
                builder.append(")");
                builder.append("\n");
            }
        }
    }

    private void appendAnnotations(String prefix, StringBuilder builder, Map<String, Map<Set<String>, String>> annotations) {
        if (annotations != null) {
            for (Map.Entry<String, Map<Set<String>, String>> entry : annotations.entrySet()) {
                Map<Set<String>, String> value = entry.getValue();
                for (Map.Entry<Set<String>, String> setStringEntry : value.entrySet()) {
                    builder.append(prefix).append(entry.getKey()).append("(");
                    builder.append(setStringEntry.getValue());
                    builder.append(")");
                    builder.append("\n");
                }
            }
        }
    }

    private void appendDoc(String prefix, StringBuilder builder, String name) {
        builder.append(prefix).append("/*").append("\n");
        builder.append(prefix).append("*").append("  ").append(name).append("\n");
        builder.append(prefix).append("*/").append("\n");
    }
}
